﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Windows.Media;
using System.Windows.Controls;

namespace FireFly
{
    /// <summary>
    /// Base class for view models
    /// </summary>
    /// <typeparam name="TModel">model type</typeparam>
    public abstract partial class ViewModelBase<TModel> : IViewModel, IModelContainer
    {
        static Dictionary<Type, ContextMenu> _ContextMenus = new Dictionary<Type, ContextMenu>();
        static IRelayCommand _SelectCommand;

        protected TModel Model
        {
            get;
            set;
        }

        protected ViewModelBase(TModel model)
        {
            Model = model;
        }

        /// <summary>
        /// Icon for UI
        /// </summary>
        public virtual ImageSource Icon
        {
            get
            {
                return ViewModelService.Instance.GetIcon(GetType());
            }
            set
            {
            }
        }
      
        public abstract string DisplayName
        {
            get;
        }
      
        public virtual bool IsReadOnly
        {
            get
            {
                return false;
            }
        } 
      
        /// <summary>
        /// Returns context menu for this view model.
        /// </summary>
        /// <remarks>By default context menu contains all commands of view model.</remarks>
        public virtual ContextMenu ContextMenu
        {
            get
            {
                var t = GetType();
                if(!_ContextMenus.ContainsKey(t))
                    _ContextMenus.Add(t, ViewModelService.Instance.CreateContextMenu(this, Commands));
                return _ContextMenus[t];
            }
        }
      
        public virtual IEnumerable<IRelayCommand> Commands
        {
            get
            {
                return new IRelayCommand[] {};
            }
        }

        public virtual IRelayCommand SelectCommand
        {
            get
            {
                if(_SelectCommand == null)
                {
                    _SelectCommand = ViewModelService.Instance.CreateStandartSelectCommand<TModel>();
                }
                return _SelectCommand;
            }
        }

        #region notify property changed
        public event PropertyChangedEventHandler PropertyChanged;


        /// <summary>
        /// Raise PropertyChanged event
        /// </summary>
        protected virtual void OnPropertyChanged(string propName)
        {
            CheckPropertyName(propName);
            if(PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        #region debug method: CheckPropertyName()
        [Conditional("DEBUG")]
        [DebuggerStepThrough]
        void CheckPropertyName(string propName)
        {
            if(TypeDescriptor.GetProperties(this)[propName] == null)
                throw new ArgumentOutOfRangeException(propName, string.Format("Property '{0}' not found", propName));
        }
        #endregion
        #endregion

        #region IModelContainer Members
        object IModelContainer.GetModel()
        {
            return Model;
        }
        #endregion
    }
}